namespace RBAC.Write.Api.Application.Handler.BomHandler
{
    using System;
    using System.Collections.Generic;
    using System.IO;
    using System.Linq;
    using System.Threading;
    using System.Threading.Tasks;
    using ClosedXML.Excel;
    using MediatR;
    using Microsoft.AspNetCore.Http;
    using Microsoft.Extensions.Logging;
    using RBAC.Domain.BomManage;
    using RBAC.ErrorCode;
    using RBAC.Interstructrue.Base;
    using RBAC.Write.Api.Application.Command.BomCommand;
    using RBAC.Write.Api.Application.Command.ERP.MaterialFile; // ImportResultDto

    /// <summary>
    /// 产品导入 处理器（配合 DownloadProductImportTemplate 模板）
    /// 模板列：产品名称（必填）、型号/规格、描述
    /// </summary>
    public class ProductImportHandler : IRequestHandler<ProductImportCommand, APIResult<ImportResultDto>>
    {
        private readonly IBaseRepository<Product> _productRepo;
        private readonly ILogger<ProductImportHandler> _logger;

        public ProductImportHandler(IBaseRepository<Product> productRepo, ILogger<ProductImportHandler> logger)
        {
            _productRepo = productRepo;
            _logger = logger;
        }

        public async Task<APIResult<ImportResultDto>> Handle(ProductImportCommand request, CancellationToken cancellationToken)
        {
            var result = new APIResult<ImportResultDto> { Data = new ImportResultDto() };
            try
            {
                cancellationToken.ThrowIfCancellationRequested();

                // 1) 基础校验
                if (request.File == null || request.File.Length == 0)
                    return new APIResult<ImportResultDto> { Code = APIEnums.Fail, Msg = "请选择有效的Excel文件", Data = new ImportResultDto() };

                var ext = Path.GetExtension(request.File.FileName).ToLower();
                if (ext != ".xlsx" && ext != ".xls")
                    return new APIResult<ImportResultDto> { Code = APIEnums.Fail, Msg = "请上传Excel文件（.xlsx或.xls）", Data = new ImportResultDto() };

                // 2) 读取Excel
                var rows = await ReadExcelAsync(request.File);
                if (rows.Count == 0)
                    return new APIResult<ImportResultDto> { Code = APIEnums.Fail, Msg = "Excel中未读取到有效数据", Data = new ImportResultDto() };

                // 3) 逐行校验并构造实体
                var toInsert = new List<Product>();
                var nowPrefix = DateTime.Now.ToString("yyMMddHHmmss");
                int seq = 1;
                int excelRowNo = 2; // 数据行从第2行开始

                foreach (var r in rows)
                {
                    var errors = new List<string>();

                    var name = r.Name?.Trim() ?? string.Empty;
                    var model = string.IsNullOrWhiteSpace(r.Model) ? null : r.Model!.Trim();
                    var desc = string.IsNullOrWhiteSpace(r.Description) ? null : r.Description!.Trim();

                    if (string.IsNullOrWhiteSpace(name))
                        errors.Add("产品名称不能为空");

                    if (errors.Any())
                    {
                        result.Data.FailCount++;
                        result.Data.ErrorDetails.Add(new ImportErrorDetail
                        {
                            RowNumber = excelRowNo,
                            ErrorMessage = string.Join("；", errors),
                            OriginalData = new Dictionary<string, string>
                            {
                                { "产品名称", name },
                                { "型号/规格", model ?? string.Empty },
                                { "描述", desc ?? string.Empty }
                            }
                        });
                    }
                    else
                    {
                        // 生成唯一编码：CP + 时间前缀 + 三位序号
                        var code = $"CP{nowPrefix}{seq.ToString().PadLeft(3,'0')}";
                        seq++;

                        toInsert.Add(new Product
                        {
                            Code = code,
                            Name = name,
                            Model = model,
                            Description = desc
                        });

                        result.Data.SuccessCount++;
                    }

                    excelRowNo++;
                }

                // 4) 批量入库
                if (toInsert.Any())
                {
                    _productRepo.CreateBatch(toInsert);
                }

                result.Code = APIEnums.Success;
                result.Msg = $"导入完成，成功{result.Data.SuccessCount}条，失败{result.Data.FailCount}条";
            }
            catch (OperationCanceledException)
            {
                _logger?.LogWarning("产品导入被取消");
                result.Code = APIEnums.Fail;
                result.Msg = "请求已取消";
            }
            catch (Exception ex)
            {
                _logger?.LogError(ex, "产品导入异常: {Message}", ex.Message);
                result.Code = APIEnums.Fail;
                result.Msg = "导入失败: " + ex.Message;
            }

            return result;
        }

        private sealed class RowData
        {
            public string? Name { get; set; }
            public string? Model { get; set; }
            public string? Description { get; set; }
        }

        private static async Task<List<RowData>> ReadExcelAsync(IFormFile file)
        {
            var list = new List<RowData>();
            using var ms = new MemoryStream();
            await file.CopyToAsync(ms);
            ms.Position = 0;
            using var wb = new XLWorkbook(ms);
            var ws = wb.Worksheet(1);
            var used = ws.RangeUsed();
            if (used == null) return list;

            // 假定表头固定3列：产品名称（必填）、型号/规格、描述
            foreach (var row in used.RowsUsed().Skip(1))
            {
                var rd = new RowData
                {
                    Name = row.Cell(1).GetValue<string>()?.Trim(),
                    Model = row.Cell(2).GetValue<string>()?.Trim(),
                    Description = row.Cell(3).GetValue<string>()?.Trim()
                };

                // 至少要有任一列有值才认为是有效行
                if (!string.IsNullOrWhiteSpace(rd.Name) || !string.IsNullOrWhiteSpace(rd.Model) || !string.IsNullOrWhiteSpace(rd.Description))
                    list.Add(rd);
            }

            return list;
        }
    }
}
